import java.util.*;

public class RainmanPlanet extends Planet {

	public static final int MAXTURN = 200; 		// Number of rounds to predict

	public int distance=0;						// 

	// DEFENSIVE VALUES
	public boolean inDanger = false;			// Is this planet in danger of getting captured
	public int inDangerNbTurn = 0;				// If so WHEN
	public int inDangerShipsNeeded=0;			// How many ships needed NOT to loose planet

	// ATTACK VALUES
	public double payback = 0.0;				// Number of turn before planets PAYS itself
	public boolean willBeWon = false;			// Will I win this planet with current fleets
	public int	freeShips = 0;					// Number of ships this planet can send to attacks WITHOUT getting lost

	public Future future[];						// new code

	public class Future{						// prediction inner class
		public int owner =0;
		public int numShips=0;
		public int tmpMyShips = 0;
		public int tmpEnemyShips = 0;
	} 

	// ctor --------------------------------------------------------------
	public RainmanPlanet(Planet p){
		super(p.PlanetID(), p.Owner(),p.NumShips(),p.GrowthRate(),p.X(),p.Y());

		// allocate prediction array
		future = new Future[MAXTURN];
		for(int i=0;i<MAXTURN;i++){
			future[i] = new Future();
		}

		// Number of turn before Planets pays back what it costs to win it
		this.payback = (double)this.NumShips() / (double)this.GrowthRate();

	}// ctor

	//-----------------------------------------------------------------
	public void predictFuture(List<Fleet> ListFleet){

		future[0].owner = this.Owner();
		future[0].numShips = this.NumShips();


		for( Fleet f: ListFleet){
			if( f.DestinationPlanet() == this.PlanetID()){
				int index = Math.min(f.TurnsRemaining(), MAXTURN);

				if(f.Owner() == 1 ){
					future[index].tmpMyShips += f.NumShips();
				}
				else{
					future[index].tmpEnemyShips += f.NumShips();
				}

			}
		}
		// resolve ALL battles
		// Start at NEXT round because current round is already known
		for(int i=1; i<MAXTURN;i++){

			// Apply GROWTH BEFORE battle is resolved IF planet is NOT neutral
			// based on PREVIOUS TURN OWNER
			if(future[i-1].owner != 0){
				future[i].numShips = future[i-1].numShips + this.GrowthRate();
			}
			else{
				future[i].numShips = future[i-1].numShips;
			}

			if( !resolveBattle(i) ){
				future[i].owner = future[i-1].owner;
			}
		}

		// Set planet Flags for AI choices
		determineFlags();

	}
	//-----------------------------------------------------------------
	// Returns TRUE if planet changed owner
	public boolean resolveBattle(int turnNo){

		// NEUTRAL PLANET
		if(future[turnNo].owner == 0){

			// I have more ships
			if(future[turnNo].tmpMyShips >future[turnNo].tmpEnemyShips){
				int remainingShips = future[turnNo].tmpMyShips - future[turnNo].tmpEnemyShips;

				// Atack neutral planet
				future[turnNo].numShips -= remainingShips;

				if(future[turnNo].numShips < 0 ){
					future[turnNo].numShips *= -1;
					future[turnNo].owner = 1;
					return true;
				}
			}
			else{// Enemy has more ships
				int remainingShips = future[turnNo].tmpEnemyShips - future[turnNo].tmpMyShips;

				// Atack neutral planet
				future[turnNo].numShips -= remainingShips;				

				// Atack neutral planet
				if(future[turnNo].numShips < 0 ){
					future[turnNo].numShips *= -1;
					future[turnNo].owner = 2;
					return true;
				}
			}
		}	
		// MY PLANET
		if(future[turnNo].owner == 1){
			int remainingShips =  future[turnNo].tmpMyShips -future[turnNo].tmpEnemyShips;	

			future[turnNo].numShips -= remainingShips;

			// If enemyWon
			if( future[turnNo].numShips <0){
				future[turnNo].numShips *= -1;
				future[turnNo].owner = 2;
				return true;
			}

		}

		// ENEMY PLANET
		if(future[turnNo].owner == 2){
			int remainingShips =  future[turnNo].tmpEnemyShips - future[turnNo].tmpMyShips;	

			future[turnNo].numShips -= remainingShips;

			// If I Win
			if( future[turnNo].numShips <0){
				future[turnNo].numShips *= -1;
				future[turnNo].owner = 1;
				return true;
			}

		}

		return false;
	}
	//-----------------------------------------------------------------
	private void determineFlags(){

		// CALCULATE INDANGER STATE
		if(future[0].owner == 1){
			this.freeShips = this.NumShips();
			this.inDangerNbTurn = MAXTURN;
			boolean shipsNeededcalculated = false;
			
			for(int i=1; i<MAXTURN;i++){
				if(future[i].owner != 1){
					this.inDanger = true;
					this.inDangerNbTurn = Math.min(i, this.inDangerNbTurn);
//					if (shipsNeededcalculated == false){
						this.inDangerShipsNeeded = Math.max(this.inDangerShipsNeeded,future[i].numShips);
						shipsNeededcalculated = true;
//					}
					this.freeShips =0;
				}	
			}

			for(int i=1; i<MAXTURN;i++){
				this.freeShips = Math.min(this.freeShips, this.future[i].numShips);
			}
			
		} // Endof INDANGER STATE
		
		// CALCULATE WILLBEWON STATE

		
	}	
}
